﻿using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Text;

namespace CSharpReflector
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        public enum EnumScriptLanguage
        {
            /// <summary>
            /// C#.NET
            /// </summary>
            CSharp = 0,
            /// <summary>
            /// VisualBasic.NET
            /// </summary>
            VB = 1,
            /// <summary>
            /// JScript.NET
            /// </summary>
            JScript = 2
        }

        private static void AddAssemblyAttributes(System.CodeDom.CodeCompileUnit unit,string asmTitle,string asmDesc)
        {
            unit.AssemblyCustomAttributes.Add(new System.CodeDom.CodeAttributeDeclaration(
                "System.Reflection.AssemblyTitleAttribute",
                new System.CodeDom.CodeAttributeArgument(
                new System.CodeDom.CodePrimitiveExpression(asmTitle))));
            unit.AssemblyCustomAttributes.Add(new System.CodeDom.CodeAttributeDeclaration(
                "System.Reflection.AssemblyDescriptionAttribute",
                new System.CodeDom.CodeAttributeArgument(
                new System.CodeDom.CodePrimitiveExpression(asmDesc))));
            unit.AssemblyCustomAttributes.Add(new System.CodeDom.CodeAttributeDeclaration(
                "System.Reflection.AssemblyCompanyAttribute",
                new System.CodeDom.CodeAttributeArgument(
                new System.CodeDom.CodePrimitiveExpression(
                "公司"))));
            unit.AssemblyCustomAttributes.Add(new System.CodeDom.CodeAttributeDeclaration(
                "System.Reflection.AssemblyProductAttribute",
                new System.CodeDom.CodeAttributeArgument(
                new System.CodeDom.CodePrimitiveExpression(
                "产品名"))));
            unit.AssemblyCustomAttributes.Add(new System.CodeDom.CodeAttributeDeclaration(
                "System.Reflection.AssemblyCopyrightAttribute",
                new System.CodeDom.CodeAttributeArgument(
                new System.CodeDom.CodePrimitiveExpression(
                "产品名"))));
            unit.AssemblyCustomAttributes.Add(new System.CodeDom.CodeAttributeDeclaration(
                "System.Reflection.AssemblyTrademarkAttribute",
                new System.CodeDom.CodeAttributeArgument(
                new System.CodeDom.CodePrimitiveExpression(
                "产品名"))));
            unit.AssemblyCustomAttributes.Add(new System.CodeDom.CodeAttributeDeclaration(
                "System.Reflection.AssemblyVersionAttribute",
                new System.CodeDom.CodeAttributeArgument(
                new System.CodeDom.CodePrimitiveExpression("1.0"))));
        }

        private decimal ReturnTest(string aStr)
        {
            string userFuncs = "public static decimal pub() \r\n { \r\n return " + aStr + "; \r\n }";
            EnumScriptLanguage lang = EnumScriptLanguage.CSharp;

            //================================================================
            System.CodeDom.Compiler.CodeDomProvider provider = null;
            switch (lang)
            {
                case EnumScriptLanguage.CSharp:
                    provider = new Microsoft.CSharp.CSharpCodeProvider();
                    break;
                case EnumScriptLanguage.VB:
                    provider = new Microsoft.VisualBasic.VBCodeProvider();
                    break;
                default:
                    return 0;
            }
            //================================================================
            System.CodeDom.Compiler.CompilerParameters
                param = new System.CodeDom.Compiler.CompilerParameters();
            param.GenerateInMemory = false;
            param.GenerateExecutable = false;
            //================================================================

            System.CodeDom.Compiler.CompilerResults cr = null;

            System.CodeDom.CodeCompileUnit unit = new System.CodeDom.CodeCompileUnit();
            System.CodeDom.CodeNamespace ns =
                new System.CodeDom.CodeNamespace("XiaoNei");
            System.CodeDom.CodeTypeDeclaration typeDefine = null;

            //添加参照等===================================================================
            string[] referencedAssemblies = { "System.dll", "System.Data.dll", "Microsoft.VisualBasic.dll" };
            // 参照、インポート宣言を追加する
            if ((unit == null) || (referencedAssemblies == null))
            { }
            else
            {

                if ((referencedAssemblies != null) && (referencedAssemblies.Length > 0))
                {
                    for (int i = 0; i < referencedAssemblies.Length; i++)
                    {
                        unit.ReferencedAssemblies.Add(referencedAssemblies[i]);
                        if (referencedAssemblies[i].ToUpper() == "SYSTEM.DLL")
                        {
                            ns.Imports.Add(new System.CodeDom.CodeNamespaceImport("System"));
                            ns.Imports.Add(new System.CodeDom.CodeNamespaceImport("System.Collections"));
                            ns.Imports.Add(new System.CodeDom.CodeNamespaceImport("System.Text"));
                        }
                        else if (referencedAssemblies[i].ToUpper() == "SYSTEM.DATA.DLL")
                        {
                            ns.Imports.Add(new System.CodeDom.CodeNamespaceImport("System.Data"));
                        }
                        else if (referencedAssemblies[i].ToUpper() == "MICROSOFT.VISUALBASIC.DLL")
                        {
                            ns.Imports.Add(new System.CodeDom.CodeNamespaceImport("Microsoft.VisualBasic"));
                        }
                    }
                }
            }
            //====================================================================================

            // ネームスペースの宣言
            unit.Namespaces.Add(ns);

            // アセンブリ属性を追加する
            AddAssemblyAttributes(unit, "aaa", "bbb");

            // ユーザ定義関数クラスのコードを生成する。
            // クラス宣言
            typeDefine = new System.CodeDom.CodeTypeDeclaration("UserFunction");

            // 登録されているユーザ定義関数をすべてメソッド定義する。
            string scriptCode = userFuncs;
            if (scriptCode.EndsWith("\n") == false)
            {
                // 最後に改行がなければ追加しておく
                scriptCode += "\r\n";
            }
            typeDefine.Members.Add(new System.CodeDom.CodeSnippetTypeMember(scriptCode));
            ns.Types.Add(typeDefine);

            // ソースコードを出力する。
            StringBuilder sb = new StringBuilder();
            System.IO.TextWriter writer = new System.IO.StringWriter(sb);
            provider.GenerateCodeFromCompileUnit(unit, writer, new System.CodeDom.Compiler.CodeGeneratorOptions());

            // コンパイルしてアセンブリファイルを出力する。
            cr = provider.CompileAssemblyFromDom(param, unit);

            // そもそも NativeCompilerReturnValue が 0 でないときは、
            // コンパイラの呼び出しに失敗している可能性がある。
            if (cr.NativeCompilerReturnValue != 0)
            {
                StringBuilder s = new StringBuilder();
                for (int ii = 0; ii < cr.Output.Count; ii++)
                {
                    System.Console.WriteLine(cr.Output[ii]);
                }
            }
            if (cr.Errors.Count > 0)
            {
                // コンパイルエラーをチェックする。
                for (int i = 0; i < cr.Errors.Count; i++)
                {
                    System.Console.WriteLine
                        (cr.Errors[i].Line + ":" + cr.Errors[i].ErrorText);
                    return 0;
                }
            }

            System.Reflection.Assembly userFuncAsm = cr.CompiledAssembly;
            System.Type type = userFuncAsm.GetType("XiaoNei.UserFunction");
            System.Reflection.MethodInfo method = type.GetMethod("pub");
            System.Reflection.ParameterInfo[] paramInfos = method.GetParameters();
            object[] parameters = new object[paramInfos.Length];
            for (int i = 0; i < paramInfos.Length; i++)
            {
                try
                {
                    parameters[i] = Convert.ChangeType("test", typeof(object));
                }
                catch (Exception ex)
                {
                    return 0;
                }
            }
            object result = method.Invoke(null, parameters);

            try
            {
                return decimal.Parse(result.ToString());
            }
            catch
            {
                return 0;
            }
        }

    }
}
